
package com.insigma.business.qrcode.common._provider.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import com.insigma.business.qrcode.common.dao.CommonAdminAreaDO;
import com.insigma.business.qrcode.common.dto.*;
import com.insigma.business.qrcode.common._provider.BaseProviderImpl;
import com.insigma.business.qrcode.common.service.CommonAdminAreaService;
import com.insigma.business.qrcode.common._provider.CommonQaInfoProvider;
import com.insigma.business.qrcode.common.template.BasePagingResponse;
import com.insigma.business.qrcode.common.template.MemCacheManager;
import com.insigma.business.qrcode.common.template.area.ServiceCallback;
import com.insigma.business.qrcode.common.util.BizCheckUtil;
import com.insigma.business.qrcode.common.util.ResponseUtils;
import com.insigma.business.qrcode.common.util.SessionUtils;
import com.insigma.business.qrcode.common.vo.BaseDeleteRequest;
import com.insigma.business.qrcode.common.vo.BaseResponse;
import com.insigma.business.qrcode.intell.dto.*;
import com.insigma.business.qrcode.intell.entity.CommonKeywordDO;
import com.insigma.business.qrcode.intell.entity.CommonQaInfoDO;
import com.insigma.business.qrcode.intell.service.CommonKeywordService;
import com.insigma.business.qrcode.intell.service.CommonQaInfoService;
import com.insigma.business.qrcode.intell._consumer.SceneConsumer;
import com.insigma.business.qrcode.common.converter.CommonQaInfoProviderConverter;
import com.insigma.business.qrcode.intell.util.AdminAreaCodeUtils;
import com.insigma.business.qrcode.intell.util.Html2Text;
import com.insigma.business.qrcode.intell.util.PageUtils;
import com.insigma.business.qrcode.intell.util.WordSegmentUtils;
import com.insigma.business.qrcode.soldier.dto.KeywordItemDTO;
import com.insigma.business.qrcode.soldier.dto.QaItemDTO;
import com.insigma.business.qrcode.soldier.dto.QaItemExtraDTO;
import com.insigma.business.qrcode.soldier.dto.SystemConfigService;
import com.insigma.business.qrcode.soldier.entity.QaCategoryDTO;
import com.insigma.business.qrcode.soldier.entity.SystemConfigDO;
import com.insigma.business.qrcode.soldier.request.BaseGetRequest;
import com.insigma.business.qrcode.soldier.request.CommonQaInfoUpdateRequest;
import com.insigma.business.qrcode.soldier.service.CommonDataDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
@Component("commonQaInfoProvider")
public class CommonQaInfoProviderImpl extends BaseProviderImpl implements CommonQaInfoProvider {

    @Resource
    CommonQaInfoService commonQaInfoService;

    @Resource
    SystemConfigService systemConfigService;

    @Resource
    CommonAdminAreaService commonAdminAreaService;

    @Resource
    CommonKeywordService commonKeywordService;

    @Resource
    SceneConsumer sceneConsumer;
    private Integer maxIntelligentCount = 7;

    private Integer maxKeywordShowCount = 4;

    @Resource
    private CommonDataDictService commonDataDictService;

    @Override
    public BaseResponse<QaResult> intelligentQA(CommonQaInfoSearchRequest searchRequest) {



        if (Strings.isNotBlank(searchRequest.getKeyword())) {

            Map<String, KeywordBO> keywordBOMap = queryAllCachedKeywordMap(searchRequest.getAdminAreaCode());
            KeywordBO keywordBO = keywordBOMap.get(searchRequest.getKeyword().trim());
            if (keywordBO != null) {
                searchRequest.setInput(getKeywords(keywordBO));
            }
        }

        List<CommonQaInfoDTO> commonQaInfoDTOS = queryAllCachedQa();

        if (Strings.isBlank(searchRequest.getInput())) {
            if ("SCENE".equals(searchRequest.getType())) {
                QaResult result = buildSceneInitInfo(commonQaInfoDTOS);
                return ResponseUtils.buildSuccessResponse(result);
            }

            List<CommonQaInfoDTO> sub = filterQaList(commonQaInfoDTOS, searchRequest.getAdminAreaCode());
            QaResult list = buildListQaFirstResult(sub, searchRequest.getAdminAreaCode());
            return ResponseUtils.buildSuccessResponse(list);
        }


        if (searchRequest.getInput().contains("你好") || searchRequest.getInput().contains("您好")) {
            QaResult one = buildOneHelloResult();
            return ResponseUtils.buildSuccessResponse(one);
        }


        CommonQaInfoDTO oneItem = getQAItemOfInput(commonQaInfoDTOS, searchRequest.getInput());
        if (oneItem != null) {
            QaResult list = buildOneQaResult(oneItem);
            return ResponseUtils.buildSuccessResponse(list);
        }


        List<Map.Entry<String, Integer>> entries = matchKeywordList(searchRequest.getInput(), commonQaInfoDTOS);
        if (!CollectionUtils.isEmpty(entries)) {
            QaResult resultObject = sortAndBuildListQaResult(entries);
            resultObject.setKeywords(getNextKeywords(searchRequest));
            return ResponseUtils.buildSuccessResponse(resultObject);
        }


        QaResult list = buildNoMatchQa();
        return ResponseUtils.buildSuccessResponse(list);
    }

    @Override
    public BaseResponse<String> evaluateQa(CommonQaInfoUpdateRequest request) {
        BizCheckUtil.checkNotNull(request, "请求不能为空");
        BizCheckUtil.checkNotNull(request.getHelpful(), "helpful不能为空");

        if (Strings.isNotBlank(request.getTitle())) {
            commonQaInfoService.addHelpfulCount(request.getTitle(), request.getHelpful());
        } else if (Strings.isNotBlank(request.getId())) {
            commonQaInfoService.addHelpfulCountById(request.getId(), request.getHelpful());
        }

        return ResponseUtils.buildSuccessResponse("success");    }

    private QaResult buildNoMatchQa() {
        Map<String, QaItemExtraDTO> extraDTOMap = Maps.newHashMap();
        QaItemExtraDTO dto = new QaItemExtraDTO("我的咨询", "/subPackages/user/consultHelp/consult/index", "absolute", "#FFA940");
        extraDTOMap.put("wdzx", dto);
        QaItemDTO qaItemDTO = new QaItemDTO("您好，没有找到答案，请转入${wdzx}！", extraDTOMap);
        return new QaResult(QaItemTypeEnum.ONE.name(), Lists.newArrayList(qaItemDTO), QaMessageTypeEnum.PLACEHOLDER.name());
    }

    private QaResult sortAndBuildListQaResult(List<Map.Entry<String, Integer>> entries) {
        Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        List<Map.Entry<String, Integer>> sub = CollectionUtil.sub(entries, 0, maxIntelligentCount);

        List<QaItemDTO> result = Lists.newArrayList();
        for (Map.Entry<String, Integer> entry : sub) {
            QaItemDTO qaItemDTO = new QaItemDTO(entry.getKey());
            result.add(qaItemDTO);
        }

        return new QaResult("您的问题是否为：", QaItemTypeEnum.LIST.name(), result, QaMessageTypeEnum.CLICK.name());
    }

    private List<Map.Entry<String, Integer>> matchKeywordList(String input, List<CommonQaInfoDTO> commonQaInfoDTOS) {
        Map<String, Set<String>> keywordMap = commonQaInfoDTOS.stream().collect(Collectors.toMap(CommonQaInfoDTO::getTitle, CommonQaInfoDTO::getKeywordList, (value1, value2) -> value2));

        Set<String> inputWordSeg = WordSegmentUtils.segmentWord(input);

        Map<String, Integer> scoreMap = Maps.newHashMap();
        for (Map.Entry<String, Set<String>> entry : keywordMap.entrySet()) {
            Sets.SetView<String> intersection = Sets.intersection(entry.getValue(), inputWordSeg);
            scoreMap.put(entry.getKey(), intersection.size());
        }

        List<Map.Entry<String, Integer>> collect = scoreMap.entrySet().stream().filter(s -> s.getValue() > 0).collect(Collectors.toList());

        if (collect.size() < maxIntelligentCount) {

            for (Map.Entry<String, Set<String>> entry : keywordMap.entrySet()) {
                Set<String> keyWordSet = entry.getValue();
                int secondLevel = calKeyWordMatchCount(keyWordSet, inputWordSeg);
                Integer integer = scoreMap.get(entry.getKey());
                if (secondLevel > 0 && (integer == null || integer <= 0)) {
                    scoreMap.put(entry.getKey(), 1);
                }
            }
        }

        return scoreMap.entrySet().stream().filter(s -> s.getValue() > 0).collect(Collectors.toList());
    }

    private int calKeyWordMatchCount(Set<String> keyWordSet, Set<String> inputWordSeg) {
        int count = 0;
        for (String s : keyWordSet) {
            for (String s1 : inputWordSeg) {
                if (s.contains(s1) || s1.contains(s)) {
                    count++;
                }
            }
        }
        return count;
    }

    private QaResult buildOneQaResult(CommonQaInfoDTO oneItem) {
        Map<String, QaItemExtraDTO> extraMap = null;
        String extra = oneItem.getExtra();
        if (Strings.isNotBlank(extra)) {
            extraMap = JSON.parseObject(extra, new TypeReference<Map<String, QaItemExtraDTO>>() {
            });
        }

        QaItemDTO qaItemDTO = new QaItemDTO(oneItem.getTitle(), oneItem.getContent(), extraMap);
        qaItemDTO.setCategory(oneItem.getCategory());
        qaItemDTO.setReference(oneItem.getReference());
        qaItemDTO.setAttachment(oneItem.getAttachment());
        return new QaResult(QaItemTypeEnum.ONE.name(), Lists.newArrayList(qaItemDTO), oneItem.getMessageType());
    }

    private CommonQaInfoDTO getQAItemOfInput(List<CommonQaInfoDTO> commonQaInfoDTOS, String input) {
        String trimStr = input.trim();
        for (CommonQaInfoDTO commonQaInfoDTO : commonQaInfoDTOS) {
            if (commonQaInfoDTO.getTitle().equals(trimStr)) {
                return commonQaInfoDTO;
            }
        }

        return null;
    }

    private QaResult buildListQaFirstResult(List<CommonQaInfoDTO> sub, String adminAreaCode) {
        List<QaItemDTO> result = Lists.newArrayList();
        for (CommonQaInfoDTO dto : sub) {
            QaItemDTO qaItemDTO = new QaItemDTO(dto.getTitle());
            result.add(qaItemDTO);
        }

        QaResult qaResult = new QaResult("您是想咨询以下问题吗？", QaItemTypeEnum.LIST.name(), result, QaMessageTypeEnum.CLICK.name());
        List<KeywordItemDTO> commonKeywordDTOS = getFirstKeywords(adminAreaCode);
        qaResult.setKeywords(commonKeywordDTOS);
        return qaResult;

    }

    private List<KeywordItemDTO> getFirstKeywords(String adminAreaCode) {
        List<KeywordBO> keywordBOS = queryAllCachedKeywordList(adminAreaCode);
        List<KeywordBO> sub = CollectionUtil.sub(keywordBOS, 0, maxKeywordShowCount);

        List<KeywordItemDTO> commonKeywordDTOS = Lists.newArrayList();
        for (KeywordBO keywordBO : sub) {
            KeywordItemDTO dto = new KeywordItemDTO();
            BeanUtils.copyProperties(keywordBO, dto);
            commonKeywordDTOS.add(dto);
        }
        return commonKeywordDTOS;
    }

    private List<CommonQaInfoDTO> queryAllCachedQa() {
        String key = "All_QA";
        Cache<String, Object> cache = MemCacheManager.getInstance();

        Object o = cache.getIfPresent(key);
        if (o == null) {
            List<CommonQaInfoDO> allQAOld = commonQaInfoService.search(new CommonQaInfoBSearcher(1, Integer.MAX_VALUE));
            List<CommonQaInfoDO> allQA = new ArrayList<>();
            for (CommonQaInfoDO commonQaInfoDO : allQAOld) {
                if (StringUtils.isBlank(commonQaInfoDO.getKeyword())){
                    commonQaInfoDO.setKeyword(commonQaInfoDO.getTitle());
                }
                allQA.add(commonQaInfoDO);
            }
            List<CommonQaInfoDTO> list = Lists.newArrayList();
            for (CommonQaInfoDO commonQaInfoDO : allQA) {
                final CommonQaInfoDTO dto = CommonQaInfoProviderConverter.convertResponseDO2DTO(commonQaInfoDO);
                if (dto.getKeyword().contains("[") && dto.getKeyword().contains("]")) {
                    List<String> keywordList = JSONArray.parseArray(dto.getKeyword(), String.class);
                    dto.setKeywordList(Sets.newHashSet(keywordList));
                } else {
                    if (StringUtils.isBlank(dto.getKeyword())){
                        continue;
                    }
                    String[] split = dto.getKeyword().replace("，", ",").split(",");
                    List<String> keywordList = Lists.newArrayList();
                    for (String s : split) {
                        if (Strings.isNotBlank(s)) {
                            keywordList.add(s.trim());
                        }
                    }
                    dto.setKeywordList(Sets.newHashSet(keywordList));
                }
                Object content = dto.getContent();
                if (content != null && content.toString().contains("<p>")) {
                    dto.setMessageType(QaMessageTypeEnum.RTF.name());
                }

                list.add(dto);
            }


            list.addAll(allContactNo());
            List<CommonQaInfoDTO> jobPolicy = allJobCommonPolicy();
            list.addAll(jobPolicy);

            CommonQaInfoDTO zxlb = new CommonQaInfoDTO();
            zxlb.setTitle("咨询列表");
            zxlb.setContent(jobPolicy);
            zxlb.setAdminAreaCode("330100000000");
            zxlb.setMessageType(QaMessageTypeEnum.POLICY.name());
            zxlb.setSeqNo(99);
            zxlb.setKeywordList(Sets.newHashSet("咨询列表"));
            list.add(zxlb);

            List<CommonQaInfoDTO> jsList = allJobJs();
            CommonQaInfoDTO jslb = new CommonQaInfoDTO();
            jslb.setTitle("讲师列表");
            jslb.setContent(jsList);
            jslb.setAdminAreaCode("330100000000");
            jslb.setMessageType(QaMessageTypeEnum.JS.name());
            jslb.setSeqNo(99);
            jslb.setKeywordList(Sets.newHashSet("讲师列表"));
            list.add(jslb);

            list.sort(new Comparator<CommonQaInfoDTO>() {
                @Override
                public int compare(CommonQaInfoDTO o1, CommonQaInfoDTO o2) {
                    return o1.getSeqNo().compareTo(o2.getSeqNo());
                }
            });

            cache.put(key, list);
            o = list;
        }

        List<CommonQaInfoDTO> all = (List<CommonQaInfoDTO>) o;
        return all;
    }

    private List<CommonQaInfoDTO> allJobJs() {
        UserSearchRequest userSearchRequest = new UserSearchRequest(1, Integer.MAX_VALUE);
        userSearchRequest.setType("JS");
        List<UserDTO> dto = sceneConsumer.searchUser(userSearchRequest).getDto();
        List<CommonQaInfoDTO> list = Lists.newArrayList();
        for (UserDTO userDTO : dto) {
            CommonQaInfoDTO tyjNoDto = new CommonQaInfoDTO();
            tyjNoDto.setTitle(userDTO.getName());
            tyjNoDto.setContent(JSON.toJSONString(userDTO));
            tyjNoDto.setAdminAreaCode("330100000000");
            tyjNoDto.setExtra(userDTO.getId());
            tyjNoDto.setType("JS");
            tyjNoDto.setSeqNo(99);
            tyjNoDto.setKeywordList(Sets.newHashSet(userDTO.getId(), userDTO.getName()));
            list.add(tyjNoDto);
        }
        return list;
    }

    private List<CommonQaInfoDTO> allJobCommonPolicy() {
        CommonPolicySearchRequest commonPolicySearchRequest = new CommonPolicySearchRequest(1, Integer.MAX_VALUE);
        commonPolicySearchRequest.setPublished(true);
        List<CommonPolicyDTO> policyDTOS = sceneConsumer.searchCommonPolicy(commonPolicySearchRequest).getDto();
        List<CommonQaInfoDTO> list = Lists.newArrayList();
        for (CommonPolicyDTO policyDTO : policyDTOS) {
            CommonQaInfoDTO tyjNoDto = new CommonQaInfoDTO();
            tyjNoDto.setTitle(policyDTO.getTitle());
            tyjNoDto.setContent(Html2Text.getContent(policyDTO.getContent()));
            tyjNoDto.setAdminAreaCode("330100000000");
            tyjNoDto.setType("POLICY");
            tyjNoDto.setSeqNo(99);
            if (Strings.isNotBlank(policyDTO.getKeywords())) {
                tyjNoDto.setKeywordList(Sets.newHashSet(policyDTO.getKeywords().trim().split(",")));
            } else {
                tyjNoDto.setKeywordList(Sets.newHashSet());
            }
            list.add(tyjNoDto);
        }
        return list;
    }

    private Collection<? extends CommonQaInfoDTO> allContactNo() {
        List<CommonQaInfoDTO> list = Lists.newArrayList();
        SystemConfigDO telNo = systemConfigService.getByName("TECHNICAL_SUPPORT");
        CommonQaInfoDTO telQa = new CommonQaInfoDTO();
        telQa.setTitle(telNo.getRemark());
        telQa.setContent(telNo.getValue());
        telQa.setKeywordList(Sets.newHashSet("电话，技术，支持"));
        telQa.setSeqNo(98);
        list.add(telQa);

        List<SystemConfigDO> noList = systemConfigService.listByNameLike("DISTRICT_CONTACT_NO_" + "%");

        Collections.sort(noList, new Comparator<SystemConfigDO>() {
            @Override
            public int compare(SystemConfigDO o1, SystemConfigDO o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (SystemConfigDO systemConfigDO : noList) {
            String adminAreaCode = systemConfigDO.getName().replace("DISTRICT_CONTACT_NO_", "");
            CommonAdminAreaDO commonAdminAreaDO = commonAdminAreaService.get(adminAreaCode);
            if (commonAdminAreaDO != null) {
                CommonQaInfoDTO tyjNoDto = new CommonQaInfoDTO();
                tyjNoDto.setTitle(commonAdminAreaDO.getValue() + "退役军人事务局电话号码");
                tyjNoDto.setContent(systemConfigDO.getValue() + systemConfigDO.getAdditionalValue());
                tyjNoDto.setAdminAreaCode(adminAreaCode);
                tyjNoDto.setSeqNo(99);
                String qName = getShortNameOfDistrict(commonAdminAreaDO.getValue());
                tyjNoDto.setKeywordList(Sets.newHashSet(commonAdminAreaDO.getValue(), qName, "电话", "号码"));
                list.add(tyjNoDto);
            }
        }
        return list;
    }

    private String getShortNameOfDistrict(String value) {
        if (Strings.isNotBlank(value)) {
            value = value.replace("市", "");
            value = value.replace("区", "");
            value = value.replace("县", "");
            return value;
        }
        return "";
    }

    private List<CommonQaInfoDTO> filterQaList(List<CommonQaInfoDTO> commonQaInfoDTOS, String adminAreaCode) {
        if (Strings.isBlank(adminAreaCode)) {
            return CollectionUtil.sub(commonQaInfoDTOS, 0, maxIntelligentCount);
        }

        List<CommonQaInfoDTO> collect = commonQaInfoDTOS.stream().filter(s -> Strings.isNotBlank(s.getAdminAreaCode()) && adminAreaCode.startsWith(AdminAreaCodeUtils.getCutdAreaCode(s.getAdminAreaCode()))).collect(Collectors.toList());
        return CollectionUtil.sub(collect, 0, maxIntelligentCount);
    }

    private QaResult buildSceneInitInfo(List<CommonQaInfoDTO> commonQaInfoDTOS) {
        List<QaItemDTO> result = new ArrayList<>();
        QaItemDTO policyItem = new QaItemDTO("咨询列表", "咨询列表", "TEXT");

        QaItemDTO JsItem = new QaItemDTO("讲师列表", "讲师列表", "TEXT");

        result.add(policyItem);
        result.add(JsItem);

        QaResult qaResult = new QaResult("就业创业", QaItemTypeEnum.LIST.name(), result, QaMessageTypeEnum.CLICK.name());
        return qaResult;
    }

    private List<KeywordItemDTO> getNextKeywords(CommonQaInfoSearchRequest searchRequest) {
        String keywordId = searchRequest.getKeyword();
        String adminAreaCode = searchRequest.getAdminAreaCode();
        if (Strings.isNotBlank(keywordId)) {
            Map<String, KeywordBO> keywordBOMap = queryAllCachedKeywordMap(adminAreaCode);
            KeywordBO keywordBO = keywordBOMap.get(keywordId);
            List<KeywordBO> children = keywordBO.getChildren();

            List<KeywordItemDTO> list = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(children)) {
                for (KeywordBO child : children) {
                    KeywordItemDTO dto = new KeywordItemDTO();
                    dto.setId(child.getId());
                    dto.setName(child.getName());
                    list.add(dto);
                }
            }
            return list;
        }
        return null;
    }

    private String getKeywords(KeywordBO keywordBO) {
        String str = recursiveGetKeyword(keywordBO, "");

        return str;
    }

    private String recursiveGetKeyword(KeywordBO keywordBO, String s) {
        if (keywordBO == null) {
            return s;
        }
        String result = s + "," + keywordBO.getName();
        return recursiveGetKeyword(keywordBO.getParent(), result);
    }


    private List<KeywordBO> queryAllCachedKeywordList(String adminAreaCode) {
        String key = "All_KEYWORD_LIST" + adminAreaCode;
        Cache<String, Object> cache = MemCacheManager.getInstance();
        Object o = cache.getIfPresent(key);
        if (o == null) {
            Map<String, KeywordBO> keywordBOMap = queryAllCachedKeywordMap(adminAreaCode);
            List<KeywordBO> result = Lists.newArrayList();

            for (KeywordBO value : keywordBOMap.values()) {
                if (value.getParent() == null) {
                    result.add(value);
                }
            }

            Collections.sort(result, new Comparator<KeywordBO>() {
                @Override
                public int compare(KeywordBO o1, KeywordBO o2) {
                    return o1.getId().compareTo(o2.getId());
                }
            });
            cache.put(key, result);
            o = result;
        }
        List<KeywordBO> all = (List<KeywordBO>) o;
        return all;
    }

    private Map<String, KeywordBO> queryAllCachedKeywordMap(String adminAreaCode) {
        String key = "All_KEYWORD_MAP";
        Cache<String, Object> cache = MemCacheManager.getInstance();

        Object o = cache.getIfPresent(key);
        if (o == null) {
            CommonKeywordBSearcher innerSearcher = new CommonKeywordBSearcher(1, Integer.MAX_VALUE);
            innerSearcher.setType(CommonKeywordTypeEnum.QA.name());
            List<CommonKeywordDO> allKeyword = commonKeywordService.search(innerSearcher);
            Collections.sort(allKeyword, new Comparator<CommonKeywordDO>() {
                @Override
                public int compare(CommonKeywordDO o1, CommonKeywordDO o2) {
                    return o1.getId().compareTo(o2.getId());
                }
            });

            Map<String, KeywordBO> keywordBOMap = Maps.newHashMap();
            for (CommonKeywordDO commonKeywordDO : allKeyword) {
                KeywordBO keywordBO = null;
                if (keywordBOMap.get(commonKeywordDO.getId()) == null) {
                    keywordBO = new KeywordBO();
                    BeanUtils.copyProperties(commonKeywordDO, keywordBO);
                    keywordBO.setId(commonKeywordDO.getId());
                    keywordBOMap.put(commonKeywordDO.getId(), keywordBO);
                }
            }
            for (KeywordBO value : keywordBOMap.values()) {
                String parentId = value.getParentId();
                if (Strings.isNotBlank(parentId)) {
                    KeywordBO parentBO = keywordBOMap.get(parentId);
                    if (parentBO != null) {
                        parentBO.getChildren().add(value);
                        value.setParent(parentBO);
                    }
                }
            }

            cache.put(key, keywordBOMap);
            o = keywordBOMap;
        }

        Map<String, KeywordBO> all = (Map<String, KeywordBO>) o;
        if (Strings.isNotBlank(adminAreaCode)) {
            Map<String, KeywordBO> result = new HashMap<>();
            adminAreaCode = AdminAreaCodeUtils.getCutdAreaCode(adminAreaCode);
            for (Map.Entry<String, KeywordBO> stringKeywordBOEntry : all.entrySet()) {
                KeywordBO value = stringKeywordBOEntry.getValue();
                if (Strings.isBlank(value.getAdminAreaCode()) || value.getAdminAreaCode().startsWith(adminAreaCode)) {
                    result.put(stringKeywordBOEntry.getKey(), stringKeywordBOEntry.getValue());
                }
            }
            return result;
        }
        return all;
    }

    private QaResult buildOneHelloResult() {
        QaItemDTO qaItemDTO = new QaItemDTO("您好，请输入您的问题。");
        return new QaResult(QaItemTypeEnum.ONE.name(), Lists.newArrayList(qaItemDTO), QaMessageTypeEnum.TEXT.name());
    }



    @Override
    public BasePagingResponse<List<CommonQaInfoDTO>> searchCommonQaInfo(final CommonQaInfoSearchRequest searchRequest) {

        final BasePagingResponse<List<CommonQaInfoDTO>> basePagingResponse = new BasePagingResponse<>();
        serviceTemplate.execute(basePagingResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(searchRequest, "查询分页CommonQaInfo的请求参数不能为空");
            }

            @Override
            public void executeService() {
                final CommonQaInfoBSearcher commonQaInfoBSearcher = CommonQaInfoProviderConverter.convertRequestSO2Searcher(searchRequest);
                PageHelper.startPage(commonQaInfoBSearcher.getPageNo(), commonQaInfoBSearcher.getPageSize());
                List<CommonQaInfoDO> commonQaInfoDOList = commonQaInfoService.search(commonQaInfoBSearcher);
                for(CommonQaInfoDO commonQaInfoDO : commonQaInfoDOList){
                    String category = commonQaInfoDO.getCategory();
                    String[] categoryArr = category.split(",");
                    List<QaCategoryDTO> categoryDTOS = new ArrayList<>();
                    for(String str:categoryArr){
                        categoryDTOS.add(QaCategoryDTO.builder().code(str).value(commonDataDictService.getDictLable("FAQTYPE",str)).build());
                    }
                    commonQaInfoDO.setCategoryDesc(categoryDTOS);
                }
                PageInfo<CommonQaInfoDO> pageinfo = new PageInfo<>(commonQaInfoDOList);
                final List<CommonQaInfoDTO> commonQaInfoDTOList = CommonQaInfoProviderConverter.convertResponseDOList2DTOList(commonQaInfoDOList);
                for (CommonQaInfoDTO dto : commonQaInfoDTOList) {
                    dto.setPureContent(Html2Text.getContent(dto.getContent().toString()));
                }
                ResponseUtils.buildSuccessPagingResponse(basePagingResponse, commonQaInfoDTOList, searchRequest, pageinfo.getTotal());
            }

            @Override
            public com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum getScenarioEnum() {
                return com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum.COMMON_QA_INFO_SEARCH;
            }
        });

        return basePagingResponse;
    }



    @Override
    public BaseResponse<CommonQaInfoDTO> getCommonQaInfo(final BaseGetRequest baseGetRequest) {

        final BaseResponse<CommonQaInfoDTO> baseResponse = new BaseResponse<>();
        serviceTemplate.execute(baseResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(baseGetRequest, "获取单条CommonQaInfo的请求参数不能为空");
                BizCheckUtil.checkNotBlank((String) baseGetRequest.getId(), "id不能为空");
            }

            @Override
            public void executeService() {
                final CommonQaInfoDO commonQaInfoDO = commonQaInfoService.get((String) baseGetRequest.getId());
                final CommonQaInfoDTO remoteObj = CommonQaInfoProviderConverter.convertResponseDO2DTO(commonQaInfoDO);
                ResponseUtils.setupSuccessResponse(baseResponse, remoteObj);
            }

            @Override
            public com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum getScenarioEnum() {
                return com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum.COMMON_QA_INFO_GET;
            }
        });
        return baseResponse;
    }


    @Transactional
    @Override
    public BaseResponse<String> insertCommonQaInfo(final CommonQaInfoInsertRequest insertRequest) {

        final BaseResponse<String> baseResponse = new BaseResponse<>();
        serviceTemplate.execute(transactionTemplate, baseResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(insertRequest, "新增CommonQaInfo的请求参数不能为空");
            }

            @Override
            public void executeService() {
                final CommonQaInfoDO commonQaInfoDO = CommonQaInfoProviderConverter.convertRequestIO2DO(insertRequest);
                commonQaInfoDO.setUp(0);
                commonQaInfoDO.setDown(0);
                commonQaInfoService.insert(commonQaInfoDO);
                ResponseUtils.setupSuccessResponse(baseResponse, commonQaInfoDO.getId());
            }

            @Override
            public com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum getScenarioEnum() {
                return com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum.COMMON_QA_INFO_INSERT;
            }
        });
        return baseResponse;
    }


    @Override
    public BaseResponse<Integer> updateCommonQaInfo(final CommonQaInfoUpdateRequest updateRequest) {

        final BaseResponse<Integer> baseResponse = new BaseResponse<>();
        serviceTemplate.execute(transactionTemplate, baseResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(updateRequest, "修改CommonQaInfo的请求参数不能为空");
                BizCheckUtil.checkNotBlank(updateRequest.getId(), "id不能为空");
               // BizCheckUtil.checkNotBlank(updateRequest.getModifierId(), "操作人不能为空");
              //  BizCheckUtil.checkNotBlank(updateRequest.getModifierType(), "操作人类型不能为空");
            }

            @Override
            public void executeService() {
                SessionUtils.buildModifierOfGov(updateRequest);
                CommonQaInfoDO oldInfo = commonQaInfoService.get(updateRequest.getId());
                BizCheckUtil.checkNotNull(oldInfo);
                CommonQaInfoDO commonQaInfoDO = CommonQaInfoProviderConverter.convertRequestUO2DO(updateRequest);
                commonQaInfoDO.setUp(oldInfo.getUp());
                commonQaInfoDO.setDown(oldInfo.getDown());
                commonQaInfoDO.setAdminAreaCode(oldInfo.getAdminAreaCode());
                Integer affectRowNum = commonQaInfoService.update(commonQaInfoDO);
                ResponseUtils.setupSuccessResponse(baseResponse, affectRowNum);
            }

            @Override
            public com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum getScenarioEnum() {
                return com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum.COMMON_QA_INFO_UPDATE;
            }
        });
        return baseResponse;
    }


    @Override
    public BaseResponse<Integer> deleteCommonQaInfo(final BaseDeleteRequest deleteRequest) {

        final BaseResponse<Integer> baseResponse = new BaseResponse<>();
        serviceTemplate.execute(transactionTemplate, baseResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(deleteRequest, "逻辑删除CommonQaInfo的请求参数不能为空");
                BizCheckUtil.checkNotBlank((String) deleteRequest.getId(), "id不能为空");
                BizCheckUtil.checkNotBlank(deleteRequest.getModifierType(), "操作人类型不能为空");
                BizCheckUtil.checkNotBlank((String) deleteRequest.getModifierId(), "操作人不能为空");
            }

            @Override
            public void executeService() {
                final Integer affectRowNum = commonQaInfoService.delete((String) deleteRequest.getId(), deleteRequest.getModifierType(), (String) deleteRequest.getModifierId());
                ResponseUtils.setupSuccessResponse(baseResponse, affectRowNum);
            }

            @Override
            public com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum getScenarioEnum() {
                return com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum.COMMON_QA_INFO_DELETE_LOGICALLY;
            }


        });
        return baseResponse;
    }
}
